﻿#include "widget.h"
#include "ui_widget.h"
#include <QSerialPortInfo>
#include <QDebug>
#include <QMessageBox>
#include <QFileDialog>
#include <QDateTime>




Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    //绑定布局，使其能随窗口大小发生变化
    this->setLayout(ui->globle);

    buttonindex = 0;

    //串口端口对象 this指向整个窗口
    serialPort = new QSerialPort(this);

    //给窗口添加定时器对象 this指向整个窗口
    timer = new QTimer(this);
    dateTimer = new QTimer(this);
    cirsendTimer = new QTimer(this);
//信号与槽（connect版）
    //给串口对象绑定读取信号
    connect(serialPort,&QSerialPort::readyRead,this,&Widget::on_serialData_readyToread);
    //自定义信号与槽
    connect(ui->comboBox_serialNum,&MyComBobox::refresh,this,&Widget::refreshSerialName);

//定时器
    //按时点击
    //定时器到达时间就调用点击发送槽函数 使用外部所有变量用= 修改要用&
    connect(timer,&QTimer::timeout,[=](){
        on_send_clicked();
    });
    //时间刷新
    connect(dateTimer,&QTimer::timeout,this,&Widget::timeFresh);
    dateTimer->start(100);
    //指令循环发送
    connect(cirsendTimer,&QTimer::timeout,this,&Widget::button_handler);

//控件初始化
    ui->comboBox__btlv->setCurrentIndex(6);
    ui->comboBox_dataBit->setCurrentIndex(3);
    ui->send->setEnabled(false);
    ui->HexSend->setEnabled(false);
    ui->sendNewLine->setEnabled(false);
    ui->onTimeSend->setEnabled(false);
    ui->sendText->setEnabled(false);
    ui->time->setEnabled(false);
    ui->frontInput->setEnabled(false);
    ui->labelSend->setText("Waiting...");
    writeCount = 0;
    readCount = 0;
    serialStatus = true;
    //ui->textEditRev->setReadOnly(true);

//获取串口号
    //QList<QSerialPortInfo>创建了一个存储多个QSerialPortInfo的QList类，serialList中都是QSerialPortInfo类
    QList<QSerialPortInfo> serialList = QSerialPortInfo::availablePorts();
    //把serialList中的数据给serialInfo，QSerialPortInfo是数据类型，加QSerialPortInfo是为了指定类型，不加不行
    for(QSerialPortInfo serialInfo : serialList){
        //qDebug()打印
        qDebug() << serialInfo.portName();
        //找到ui中的组件，并根据组件的方法添加项目
        ui->comboBox_serialNum->addItem(serialInfo.portName());
    }

    //另一种循环方法
    //    int size = serialList.size();
    //    for (int i = 0; i < size; ++i) {
    //        qDebug() << serialList.at(i).portName();
    //        ui->comboBox_serialNum->addItem(serialList.at(i).portName());
    //    }
    for(int i = 1;i<=9;i++){
        QString btnName = QString("pushButton_%1").arg(i);
        QPushButton* btn = findChild<QPushButton *>(btnName);
        if(btn){
            btn->setProperty("buttonId",i);
            buttons.append(btn);
            connect(btn,SIGNAL(clicked()),this,SLOT(on_command_button_clicked()));
        }

        QString lineEditName = QString("lineEdit_%1").arg(i);
        QLineEdit* lineEdit = findChild<QLineEdit *>(lineEditName);
        lineEdits.append(lineEdit);

        QString checkBoxName = QString("checkBox_%1").arg(i);
        QCheckBox* checkBox = findChild<QCheckBox *>(checkBoxName);
        checkBoxs.append(checkBox);

    }



}

Widget::~Widget()
{
    delete ui;
}


void Widget::on_btnOpCl_clicked()
{
//    if(serialStatus){
//        //1.选择端口号
//        serialPort->setPortName(ui->comboBox_serialNum->currentText());
//        //2.配置波特率
//        serialPort->setBaudRate(ui->comboBox__btlv->currentText().toInt());
//        //3.配置数据位
//        serialPort->setDataBits(QSerialPort::DataBits(ui->comboBox_dataBit->currentText().toInt()));
//        //4.配置校验位
//        switch (ui->comboBox_jyBit->currentIndex()) {
//        case 0:
//            serialPort->setParity(QSerialPort::NoParity);
//            break;
//        case 1:
//            serialPort->setParity(QSerialPort::EvenParity);
//            break;
//        case 2:
//            serialPort->setParity(QSerialPort::MarkParity);
//            break;
//        case 3:
//            serialPort->setParity(QSerialPort::OddParity);
//            break;
//        case 4:
//            serialPort->setParity(QSerialPort::SpaceParity);
//            break;
//        default:
//            serialPort->setParity(QSerialPort::UnknownParity);
//            break;
//        }
//        //5.配置停止位
//        serialPort->setStopBits(QSerialPort::StopBits(ui->comboBox_stopBit->currentText().toInt()));
//        //6.流控
//        if(ui->comboBox_null->currentText() == "No")
//            serialPort->setFlowControl(QSerialPort::NoFlowControl);
//        //7.打开串口
//        //使用open打开，设置可读可写
//        if(serialPort->open(QIODevice::ReadWrite)){
//            qDebug() << "serial open success!" ;
//            ui->comboBox_serialNum->setEnabled(false);
//            ui->comboBox__btlv->setEnabled(false);
//            ui->comboBox_null->setEnabled(false);
//            ui->comboBox_jyBit->setEnabled(false);
//            ui->comboBox_dataBit->setEnabled(false);
//            ui->comboBox_stopBit->setEnabled(false);
//            ui->send->setEnabled(true);
//            ui->btnOpCl->setText("关闭串口");
//            serialStatus = false;
//        }else{
//            QMessageBox msgBox;
//            msgBox.setWindowTitle("打开串口错误");
//            msgBox.setText("打开串口失败，串口可能被占用或已拔出！");
//            msgBox.exec();

//            qDebug() << "serial open failed!" ;
//        }
//    }
//    else
//    {
//        serialPort->close();
//        ui->comboBox_serialNum->setEnabled(true);
//        ui->comboBox__btlv->setEnabled(true);
//        ui->comboBox_null->setEnabled(true);
//        ui->comboBox_jyBit->setEnabled(true);
//        ui->comboBox_dataBit->setEnabled(true);
//        ui->comboBox_stopBit->setEnabled(true);
//        ui->btnOpCl->setText("打开串口");
//        ui->send->setEnabled(false);
//        serialStatus = true;
//        qDebug() << "serial close success!" ;
//    }
}

//点击发送按钮，读取文本框内容，向串口发送数据
void Widget::on_send_clicked()
{
    int writeFlag = 0;

    QString sendData = ui->sendText->text();
            //toStdString().c_str();
            //toLocal8Bit().constData();
    //16进制发送
    if(ui->HexSend->isChecked()){
        QString tmp = ui->sendText->text();
        //判断是否是偶数
        QByteArray tmpArray = tmp.toLocal8Bit();

        if(tmpArray.size() %2 != 0){
            ui->labelSend->setText("Error Input");
            return;
        }
        for(char c : tmpArray){
            if( !std::isxdigit(c)){
                ui->labelSend->setText("Error Input");
                return;
            }
        }
        //转换成16进制发送，用户输入1，拒绝变成字符1，ASSII 49
        QByteArray arraySend = QByteArray::fromHex(tmpArray);

        //是否需要换行 单片机有时需要换行
        if(ui->sendNewLine->isChecked()){
            arraySend.append("\r\n");
            writeFlag = serialPort->write(arraySend);

        }else{
            //write 成功为写入字节数，失败为-1
            writeFlag = serialPort->write(arraySend);
        }

    }else{//非16制进制发送
        if(ui->sendNewLine->isChecked()){
            sendData.append("\r\n");
            writeFlag = serialPort->write(sendData.toUtf8());

        }else{
        writeFlag = serialPort->write(sendData.toUtf8());
        }
    }


    if(writeFlag == -1){
        ui->labelSend->setText("SendError!");
    }else{
        writeCount += writeFlag;

        if(strcmp(sendData.toUtf8(),tmpRecode.toStdString().c_str()) != 0)
        {
            ui->textEditRecode->moveCursor(QTextCursor::End);
            ui->textEditRecode->append(sendData);
            //转成utf8编码
            tmpRecode = sendData;
        }
        ui->labelSend->setText("SendOk!");
        //ui->labelSent->setNum(writeCount);
        ui->labelSent->setText("Sent:"+QString::number(writeCount));
        qDebug() << "Send Ok:" << sendData;
    }

}

//检测到串口中的数据 读取数据
void Widget::on_serialData_readyToread()
{
    //QByteArray类型 ！！！！！
    QByteArray revMessage = serialPort->readAll();
    //使用QByteArray中的isEmpty()判断是否是空的
    if(!revMessage.isEmpty())
    {
        if(ui->autoLine->isChecked()){revMessage.append("\r\n");}
        //如果hex显示点击
        if(ui->HexShow->checkState()){
            //1.将串口中的文本转为Hex
            QString HexText = QString::fromUtf8(revMessage.toHex()).toUpper();
            //2.获取已经显示的文本内容,是Hex内容
            QString alText = ui->textEditRev->toPlainText().toUpper();
            //3.转换为QString追加到原有文本显示
            //根据显示时间是否勾选 如果hex显示点击加显示时间点击
            if(ui->reTime->checkState()){
                qDebug() << ui->reTime->checkState();
                QString TimeText = "【"+ui->labeTime->text()+"】" ;
                QString HexTimeText = QString::fromUtf8(TimeText.toUtf8().toHex()).toUpper();
                QString lastShow;
                QString tmp = HexTimeText+HexText;
                for(int i =0;i<tmp.size();i+=2){
                    lastShow += tmp.mid(i,2) + " ";
                }

                ui->textEditRev->setText(alText+lastShow);

            }else{//hex点击 显示时间不点击
                QString lastShow;
                QString tmp = HexText;
                for(int i =0;i<tmp.size();i+=2){
                    lastShow += tmp.mid(i,2) + " ";
                }
                ui->textEditRev->setText(alText+lastShow);
                //ui->textEditRev->append(HexText);
            }

        }else{//hex不点击 时间不点击
            if(!ui->reTime->checkState()){
                //QString alText = ui->textEditRev->toPlainText();
//                QTextCursor cursor = ui->textEditRev->textCursor();
//                cursor.setPosition(cursor.document()->characterCount() - 1); // 不包括结尾的换行符
//                ui->textEditRev->setTextCursor(cursor);
                ui->textEditRev->moveCursor(QTextCursor::End);
                ui->textEditRev->insertPlainText(QString::fromUtf8(revMessage));
            }else{//时间点击
                ui->textEditRev->append("【"+ui->labeTime->text()+"】"+revMessage);
                //QString alText = ui->textEditRev->toPlainText();
                //ui->textEditRev->setText(alText+"【"+ui->labeTime->text()+"】"+QString::fromUtf8(revMessage));
            }
        }

        readCount += revMessage.size();
        //ui->labelRece->setNum(readCount);
        //拼接字符串  QString::number是接收一个number数转换为QString
        ui->labelRece->setText("Received:"+QString::number(readCount));
        //如果需要QString类型 使用QString::fromUtf8()转换
        qDebug() << "Read Ok:" << QString::fromUtf8(revMessage);

        ui->textEditRev->moveCursor(QTextCursor::End);
        //ui->textEditRev->ensureCursorVisible();
        //此方法是将鼠标聚焦，可能会出现争夺鼠标的焦点问题
        //ui->textEditRev->setFocus();
    }

}


void Widget::on_btnOpCl_clicked(bool checked)
{
    if(checked){
        //1.选择端口号
        serialPort->setPortName(ui->comboBox_serialNum->currentText());
        //2.配置波特率
        serialPort->setBaudRate(ui->comboBox__btlv->currentText().toInt());
        //3.配置数据位
        serialPort->setDataBits(QSerialPort::DataBits(ui->comboBox_dataBit->currentText().toInt()));
        //4.配置校验位
        switch (ui->comboBox_jyBit->currentIndex()) {
        case 0:
            serialPort->setParity(QSerialPort::NoParity);
            break;
        case 1:
            serialPort->setParity(QSerialPort::EvenParity);
            break;
        case 2:
            serialPort->setParity(QSerialPort::MarkParity);
            break;
        case 3:
            serialPort->setParity(QSerialPort::OddParity);
            break;
        case 4:
            serialPort->setParity(QSerialPort::SpaceParity);
            break;
        default:
            serialPort->setParity(QSerialPort::UnknownParity);
            break;
        }
        //5.配置停止位
        serialPort->setStopBits(QSerialPort::StopBits(ui->comboBox_stopBit->currentText().toInt()));
        //6.流控
        if(ui->comboBox_null->currentText() == "No")
            serialPort->setFlowControl(QSerialPort::NoFlowControl);
        //7.打开串口
        //使用open打开，设置可读可写
        if(serialPort->open(QIODevice::ReadWrite)){
            qDebug() << "serial open success!" ;
            ui->comboBox_serialNum->setEnabled(false);
            ui->comboBox__btlv->setEnabled(false);
            ui->comboBox_null->setEnabled(false);
            ui->comboBox_jyBit->setEnabled(false);
            ui->comboBox_dataBit->setEnabled(false);
            ui->comboBox_stopBit->setEnabled(false);
            ui->send->setEnabled(true);
            ui->HexSend->setEnabled(true);
            ui->sendNewLine->setEnabled(true);
            ui->onTimeSend->setEnabled(true);
            ui->sendText->setEnabled(true);
            ui->time->setEnabled(true);
            ui->frontInput->setEnabled(true);
//            ui->btnOpCl->setEnabled(true);
//            ui->btnOpCl->setStyleSheet("");
            ui->btnOpCl->setText("关闭串口");
            ui->labelSend->setText("Open:Ok");
           // serialStatus = false;
        }else{
            ui->labelSend->setText("Open:fail");
            QMessageBox msgBox;
            msgBox.setWindowTitle("打开串口错误");
            msgBox.setText("打开串口失败，串口可能被占用或已拔出！");
            msgBox.exec();

            qDebug() << "serial open failed!" ;
        }
    }
    else
    {
        serialPort->close();
        ui->comboBox_serialNum->setEnabled(true);
        ui->comboBox__btlv->setEnabled(true);
        ui->comboBox_null->setEnabled(true);
        ui->comboBox_jyBit->setEnabled(true);
        ui->comboBox_dataBit->setEnabled(true);
        ui->comboBox_stopBit->setEnabled(true);
        ui->btnOpCl->setText("打开串口");
        ui->send->setEnabled(false);
        ui->HexSend->setEnabled(false);
        ui->sendNewLine->setEnabled(false);
        ui->onTimeSend->setEnabled(false);
        ui->sendText->setEnabled(false);
        ui->frontInput->setEnabled(false);
        ui->labelSend->setText("Close:Ok");

        ui->onTimeSend->setCheckState(Qt::Unchecked);
        Widget::on_onTimeSend_clicked(false);
        //serialStatus = true;
        qDebug() << "serial close success!" ;
    }
}

void Widget::on_onTimeSend_clicked(bool checked)
{
    //qDebug() << "status" << checked;
    if(checked)
    {
        ui->time->setEnabled(false);
        //打开定时器
        timer->start(ui->time->text().toInt());

        //on_send_clicked();
    }else
    {
        timer->stop();
        ui->time->setEnabled(true);

    }
}

void Widget::on_clearRe_clicked()
{
    ui->textEditRev->setText("");
}

void Widget::on_saveRe_clicked()
{
    QString fileName = QFileDialog::getSaveFileName(this,
         tr("Save File"), "E:\\Users\\Laye\\Desktop\\QTdemo\\QtUratTool\\saveFile\\serialData.txt", tr("Text (*.txt)"));
    if(fileName != "")
    {
        QFile file(fileName);
        if(!file.open(QIODevice::WriteOnly | QIODevice::Text))
            return;
        //创建文件流
        QTextStream out(&file);
        //将文本框内容输出到out中，输入用out.readLine
        out << ui->textEditRev->toPlainText();
        file.close();
    }
}

void Widget::timeFresh()
{
    QDateTime currentime = QDateTime::currentDateTime();

    QDate date = currentime.date();
    int year = date.year();

    int mounth = date.month();
    int day = date.day();

    QTime time = currentime.time();
    int hour = time.hour();
    int minute = time.minute();
    int sec = time.second();

    QString dateTime = QString("%1-%2-%3 %4:%5:%6")
            .arg(year)
            .arg(mounth,2,10,QChar('0'))
            .arg(day,2,10,QChar('0'))
            .arg(hour,2,10,QChar('0'))
            .arg(minute,2,10,QChar('0'))
            .arg(sec,2,10,QChar('0'));
    ui->labeTime->setText(dateTime);
}

void Widget::button_handler()
{

        QPushButton *btnTmp = buttons[buttonindex];
        emit btnTmp->clicked();
        buttonindex++;
        if(buttonindex >= buttons.size())
            buttonindex = 0;
}

void Widget::on_HexShow_clicked(bool checked)
{
    if(checked)
    {
        //1.获取文本框内容 为QString类型
        QString tmp = ui->textEditRev->toPlainText();
        //2.将QString转换为QByteArray，因为这样才能使用toHex方法
        QByteArray qtmp = tmp.toUtf8();
        qtmp = qtmp.toHex();
        //3.将QByte转成QString显示到文本框上
        QString lastShow;
        tmp = QString::fromUtf8(qtmp);
        for(int i = 0;i<tmp.size();i+=2){
            lastShow += tmp.mid(i,2) + " ";
        }

        ui->textEditRev->setText(lastShow.toUpper());
    }else{
        //获取
        QString tmp = ui->textEditRev->toPlainText();

        //先QString转为QByte，再把Hex转为正常显示
        QByteArray htmp = tmp.toUtf8();
        QByteArray qtmp = QByteArray::fromHex(htmp);

        //添加
        ui->textEditRev->setText(QString::fromUtf8(qtmp));
    }
    ui->textEditRev->moveCursor(QTextCursor::End);
}

void Widget::on_hideRe_clicked(bool checked)
{
    if(checked){
        ui->groupBoxRev->hide();
        ui->hideRe->setText("拓展面板");
    }else{
        ui->groupBoxRev->show();
        ui->hideRe->setText("隐藏面板");
    }
}

void Widget::on_hideHistory_clicked(bool checked)
{
    if(checked){
        ui->groupBoxRecode->hide();
        ui->hideHistory->setText("拓展历史");
    }else{
        ui->groupBoxRecode->show();
        ui->hideHistory->setText("隐藏历史");
    }
}

void Widget::refreshSerialName()
{
    ui->comboBox_serialNum->clear();
    QList<QSerialPortInfo> serialList = QSerialPortInfo::availablePorts();
    //把serialList中的数据给serialInfo，QSerialPortInfo是数据类型，加QSerialPortInfo是为了指定类型，不加不行
    for(QSerialPortInfo serialInfo : serialList){
        //qDebug()打印
        qDebug() << serialInfo.portName();
        //找到ui中的组件，并根据组件的方法添加项目
        ui->comboBox_serialNum->addItem(serialInfo.portName());
    }
}

//void Widget::on_pushButton_1_clicked()
//{
//    ui->sendText->setText(ui->lineEdit_1->text());
//    on_send_clicked();
//    if(ui->checkBox_1->isChecked())
//        ui->HexSend->setChecked(true);
//    else
//        ui->HexSend->setChecked(false);

//}


//指令按钮点击
void Widget::on_command_button_clicked()
{
    //通过sender知道是哪个按钮进行了点击
    QPushButton *btn = qobject_cast<QPushButton *>(sender());
    if(btn){
        int num = btn->property("buttonId").toInt();
        QString lineEditName = QString("lineEdit_%1").arg(num);
        QLineEdit *lineEdit = findChild<QLineEdit *>(lineEditName);
        if(lineEdit){
            if(lineEdit->text().size() <= 0)
                return;
            ui->sendText->setText(lineEdit->text());
        }
        QString checkBoxName = QString("checkBox_%1").arg(num);
        QCheckBox *checkBox = findChild<QCheckBox *>(checkBoxName);
        if(checkBox){
            if(checkBox->isChecked()){
            ui->HexSend->setChecked(true);
            }else{
                ui->HexSend->setChecked(false);

            }
        }

        on_send_clicked();
    }
}


void Widget::on_checkBox_send_clicked(bool checked)
{
    if(checked){
        ui->spinBox->setEnabled(false);
        cirsendTimer->start(ui->spinBox->text().toInt());
    }else{
        ui->spinBox->setEnabled(true);
        cirsendTimer->stop();
    }
}

void Widget::on_btnInit_clicked()
{
    QMessageBox msgBox;
    msgBox.setWindowTitle("提示");
    msgBox.setIcon(QMessageBox::Question);
    msgBox.setText("重置列表不可逆，确认是否重置？");
//    msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
    QPushButton *yesButton = msgBox.addButton("确认重置",QMessageBox::YesRole);
    QPushButton *noButton = msgBox.addButton("取消",QMessageBox::NoRole);
    //程序运行到这会循环上面的代码，然后用户做出选择才会执行下面的代码
    msgBox.exec();

    if(msgBox.clickedButton() == yesButton){
        for(int i =0;i<lineEdits.size();i++){
            lineEdits[i]->clear();
            checkBoxs[i]->setChecked(false);
        }
    }
    if(msgBox.clickedButton() == noButton){
        qDebug() << "Nothing happend ";
    }
}

void Widget::on_btnSave_clicked()
{
    QDateTime currentime = QDateTime::currentDateTime();
    QDate date = currentime.date();

    QString road = QString("E:\\Users\\Laye\\Desktop\\QTdemo\\QtUratTool\\saveFile\\%1%2%3.txt")
            .arg(date.year())
            .arg(date.month())
            .arg(date.day())
            ;

    QString fileName = QFileDialog::getSaveFileName(this,tr("Save File"),
                                                   road,
                                                   tr("Text (*.txt)"));
   QFile file(fileName);
   if(!file.open(QIODevice::WriteOnly | QIODevice::Text))
       return;
   QTextStream out(&file);
   for(int i = 0;i < lineEdits.size();i++){
       out << checkBoxs[i]->isChecked() << "," << lineEdits[i]->text() << "\n";
   }
   file.close();
}

void Widget::on_btnLoad_clicked()
{
    int i =0;
    QString road = "E:\\Users\\Laye\\Desktop\\QTdemo\\QtUratTool\\saveFile\\";

    QString fileName = QFileDialog::getOpenFileName(this,tr("打开文件"),
                                                   road,
                                                   tr("文本类型 (*.txt)"));
    if(!fileName.isEmpty()){
        QFile file(fileName);
        if(!file.open(QIODevice::ReadOnly | QIODevice::Text))
            return;

        QTextStream in(&file);
        while(!in.atEnd() && i<=9){
            //每次循环读一行
            QString line = in.readLine();
            QStringList parts = line.split(",");
            if(parts.count() == 2){
                checkBoxs[i]->setChecked(parts[0].toUInt());
                lineEdits[i]->setText(parts[1]);
            }
            i++;
        }
    }
}
